import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import PizZipUtils from "pizzip/utils/index.js";
import { saveAs } from "file-saver";
import ImageModule from 'docxtemplater-image-module-free';

export const exportWord = (wordData: any) => {

// 读取并获得模板文件的二进制内容
    function loadFile(url: string, callback: (error: any, content: any) => void) {
        PizZipUtils.getBinaryContent(url, callback);
    }

// demo.docx是模板。我们在导出的时候，会根据此模板来导出对应的数据
    loadFile("report.docx", function(
        error:Error | null,
        content
    ) {
        // 抛出异常
        if (error) {
            throw error;
        }

        // 创建一个JSZip实例，内容为模板的内容
        const zip: PizZip = new PizZip(content);
        const doc: Docxtemplater = new Docxtemplater().loadZip(zip) as Docxtemplater;
        // 添加图片处理模块
        let imageModule = new ImageModule({ getImage, getSize: () => {
            return [550, 350]
        }});
        doc.attachModule(imageModule);
        console.log(wordData)
        // 设置模板变量的值
        doc.setData(wordData);
        try {
            // 用模板变量的值替换所有模板变量
            doc.render();
        } catch (error:any) {
            // The error thrown here contains additional information when logged with JSON.stringify (it contains a properties object containing all suberrors).
            // eslint-disable-next-line no-inner-declarations
            function replaceErrors(key:any, value:any) {
                if (value instanceof Error) {
                    return Object.getOwnPropertyNames(value).reduce(function(
                        error: any,
                        key: string
                    ) {
                        error[key] = value[key as keyof Error];
                        return error;
                    }, {});
                }
                return value;
            }
            console.log(JSON.stringify({
                error: error
            }, replaceErrors));

            if (error.properties && error.properties.errors instanceof Array) {
                const errorMessages = error.properties.errors
                    .map(function(error:any) {
                        return error.properties.explanation;
                    })
                    .join("\n");
                console.log("errorMessages", errorMessages);
                // errorMessages is a humanly readable message looking like this : 'The tag beginning with "foobar" is unopened'
            }
            throw error;
        }
        // 生成一个代表docxtemplater对象的zip文件（不是一个真实的文件，而是在内存中的表示）
        const out = doc.getZip().generate({
            type: "blob",
            mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
        });
        // 将目标文件对象保存为目标类型的文件，并命名
        saveAs(out, "道路风险评估报告.docx");
    });

}

function getImage(imageData: string) {
    if (!imageData) {
      console.log('base64图片', imageData);
      return null;
    }
  
    // 将Base64图片数据转换为ArrayBuffer
    const binaryData = window.atob(imageData.replace(/^data:image\/\w+;base64,/, ""));
    const arrayBuffer = new ArrayBuffer(binaryData.length);
    const uint8Array = new Uint8Array(arrayBuffer);
  
    for (let i = 0; i < binaryData.length; i++) {
      uint8Array[i] = binaryData.charCodeAt(i);
    }
  
    // 根据Base64内容推断图片类型（通常Base64字符串会包含类型信息）
    let type;
    if (imageData.startsWith('data:image/jpeg;base64,')) {
      type = 'jpeg';
    } else if (imageData.startsWith('data:image/png;base64,')) {
      type = 'png';
    } else if (imageData.startsWith('data:image/gif;base64,')) {
      type = 'gif';
    } else {
      throw new Error(`Unsupported image format for base64 string: ${imageData}`);
    }
  
    // 返回一个近似于Buffer的对象（在浏览器中我们使用ArrayBuffer和类型代替）
    return arrayBuffer
  
  }
